"""

efficiency should take precedence over quality

"""

from __future__ import division, with_statement

from tools import *
from visualise import *

def ensure_multiple(colors, color, image):
    if colors is not None:
        return colors
    if color is None:
        color = (255,255,255) if len(image.shape)==3 else 255
    return itertools.repeat(color)

def draw_polyline(image, points, colors=None, color=None):
    colors = ensure_multiple(colors, color, image)

    C = 3 # rgb
    if len(image.shape) == 2: # grayscale
        colors = (mean(color) for color in colors)
        C = 1

    points = asarray(points)
    P = len(points)
    colors = asarray([color for color, n in zip(colors, range(P))])
    code = """
        #include <math.h>

        for (int p=1; p < P; p++) {
            int x0 = points(p, 0);
            int y0 = points(p, 1);

            int x1 = points(p-1, 0);
            int y1 = points(p-1, 1);

            // determine line resolution
            int Nx = abs(x1-x0);
            int Ny = abs(y1-y0);
            int N = Nx > Ny ? Nx : Ny;

            for (int n=0; n < N; n++) {
                int x = (x0 + n * (x1-x0) / N);
                int y = (y0 + n * (y1-y0) / N);

                for (int c=0; c < C; c++) { // copy color bands
                    image(x, y, c) = colors(p, c);
                }
            }
        }
    """
    scipy.weave.inline(code,
        ["points", "P", "image", "colors", "C"],
        type_converters=scipy.weave.converters.blitz,
        compiler = 'gcc')

def draw_cross(image, points, colors=None, color=None, arm=10):
    colors = ensure_multiple(colors, color, image)

    for (x,y), c in zip(points, colors):
        image[x-arm:x+arm, y] = c
        image[x, y-arm:y+arm] = c

def draw_circles(image, points, colors=None, color=None, radii=None, fill=False):
    colors = ensure_multiple(colors, color, image)

    if radii is None:
        radii = itertools.repeat(4)

    if fill:
        for (x,y), c, r in zip(points, colors, radii):
            image[x-r:x+r,y-r:y+r] = c
    else:
        for (x,y), c, r in zip(points, colors, radii):
            t = linspace(0,2*pi,20)
            points = vstack([cos(t), sin(t)]).T * r + (x,y)
            draw_polyline(image, points=points, color=c)

def draw_squares(image, coord_lists, fill=True, colors=None, color=None):
    colors = ensure_multiple(colors, color, image)

    if fill:
        for coords, c in zip(coord_lists, colors):
            image[coords[0,0]:coords[1,0],coords[0,1]:coords[1,1]] = c
    else:
        for coords, c in zip(coord_lists, colors):
            points = coords[0], (coords[0,0], coords[1,1]), coords[1], (coords[1,0], coords[0,1]), coords[0]
            draw_polyline(image, points, colors=colors)

class Contour(object):
    def __init__(self, points, times=None):
        self.points = points
        self.times = times

    def draw(self, image):
        draw_polyline(image, self.points)
        draw_cross(image, self.points, color=getrgb("red"))

    def bbox(self):
        return Bbox(points=asarray([self.points.min(0), self.points.max(0)+1]))

def draw_contours(image, contours):
    for contour in contours:
        contour.draw(image)

def draw_text(image, text, pos=None):
    pass #XXX

def main():
    X, Y = 300, 500
    image = zeros((X, Y, 3))
    contours = [Contour(points=numpy.random.random((3,2))*(X,Y)) for n in range(10)]
    draw_contours(image, contours)
    for c in contours:
        c.bbox().draw(image)
    draw_circles(image, points=[(X//2, Y//2)], radii=[100], color=getrgb("yellow"))
    preview(image, blocking=False)
    #~ preview(image)

if __name__ == "__main__":
    main()